package concurrent

import (
	"bytes"
	"fmt"
	"runtime"
	"strconv"
	"sync"
)

var wg sync.WaitGroup

/**
  多次执行，会发现每次打印的数字的顺序都不一致。
  这是因为10个goroutine是并发执行的，而goroutine的调度是随机的。
*/
func Test1() {
	for i := 0; i < 10; i++ {
		wg.Add(1) // 启动一个goroutine就登记+1
		go hello(i)
	}
	wg.Wait() // 等待所有登记的goroutine都结束
}

func hello(i int) {
	defer wg.Done() // goroutine结束就登记-1
	fmt.Println("Hello Goroutine!", i)
}

func Test() {
	// 分配一个逻辑处理器给调度器使用  也就是分配一个CPU？？
	runtime.GOMAXPROCS(1)

	// wg 用来等待程序完成，计数加 2，表示要等待两个 goroutine
	var wg sync.WaitGroup
	wg.Add(2)

	fmt.Println("Start Goroutines")

	//创建一个goroutine，运行匿名函数，打印小写字母表
	go func() {
		defer wg.Done()

		//windows.GetCurrentThreadId()

		//id:=windows.GetCurrentThreadId()
		//fmt.Println("thread id a", id)
		//fmt.Println("goroutine id ", goID())
		for char := 'a'; char < 'a'+26; char++ {
			fmt.Printf("%c ", char)
		}
	}()

	//创建一个goroutine，运行匿名函数，打印大写字母表
	go func() {
		defer wg.Done()

		//id:=windows.GetCurrentThreadId()
		//time.Sleep(time.Duration(3)*time.Second) //sleep 3
		//fmt.Println("thread id A", id)
		fmt.Println("goroutine id ", goID())
		for char := 'A'; char < 'A'+26; char++ {
			fmt.Printf("%c ", char)
		}
	}()

	// 等待 goroutine 结束
	fmt.Println("Waiting To Finish")
	wg.Wait()

	fmt.Println("\nTerminating Program")
}

//goroutine id
func goID() uint64 {
	b := make([]byte, 64)
	b = b[:runtime.Stack(b, false)]
	b = bytes.TrimPrefix(b, []byte("goroutine "))
	b = b[:bytes.IndexByte(b, ' ')]
	n, _ := strconv.ParseUint(string(b), 10, 64)
	return n
}
